/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  ArkMethod,
  ClassSignature,
  MethodSignature,
  Stmt,
  ArkAssignStmt,
  Local,
  ArkInvokeStmt,
  Scene,
  ts,
  AstTreeUtils,
  ArkFile,
} from "arkanalyzer/lib";
import { ArkClass } from "arkanalyzer/lib/core/model/ArkClass";
import Logger, { LOG_MODULE_TYPE } from "arkanalyzer/lib/utils/logger";
import { BaseChecker, BaseMetaData } from "../BaseChecker";
import { RuleListUtil } from "../../utils/common/DefectsList";
import {
  ClassMatcher,
  MatcherCallback,
  MatcherTypes,
} from "../../matcher/Matchers";
import { CheckerUtils } from "../../utils/checker/CheckerUtils";
import { Defects, IssueReport } from "../../model/Defects";
import { Rule } from "../../model/Rule";
type Var_base = {
  name?: string;
  type?: { name?: string };
  usedStmts?: Stmt[];
  declaringStmt?: Stmt;
};
//methodParams
type Method_Param = {
  arrayElements?: { name?: string }[];
  name: string;
  objElements: [];
};
//结果类型
enum VarType {
  Var = "var",
  Class = "class",
  Method = "method",
  Args = "args",
  ArgsP = "ArrayBindingPattern",
  Catch = "catch",
  Static = "static",
  UsedIgnorePattern = "UsedIgnorePattern",
}
type noUseVars = {
  varType: VarType; //方法名称
  stmt: Stmt;
  declareStmt: Stmt; //有方法或者类不能固定
  name: string | string[]; //解构-特殊情况
  local?: "local" | "all"; //本地或者全局
  isMethodParam?: boolean; //是否是方法参数
  arkMethod?: ArkMethod; //方便获取方法的位置信息20250207
  isRestSiblings?: boolean; //是否与解构同级
  methodName?: string; //方法名称
  parammaxUsedIndex?: number; //被使用最大参数下标
  paramIndex?: number; //用于方法参数的判定
  static?: boolean; //是否是静态
  varInit?: boolean; //2025-02-07 优化方案
  ArrayBindingPattern?: boolean;
  argPosion?: [lineNo: number, strClo: number, endClo: number]; //记录缺失的位置信息
  filePath?: string; //参数stmt不包含
};
type Options =
  | "all"
  | "local"
  | {
      args?: "after-used" | "all" | "none";
      argsIgnorePattern?: string;
      caughtErrors?: "all" | "none";
      caughtErrorsIgnorePattern?: string;
      destructuredArrayIgnorePattern?: string;
      ignoreClassWithStaticInitBlock?: boolean;
      ignoreRestSiblings?: boolean;
      reportUsedIgnorePattern?: boolean;
      vars?: "all" | "local";
      varsIgnorePattern?: string;
    };
//对参数进行解释
interface TranslatedOptions {
  args: "after-used" | "all" | "none"; //检查使用之后的----全部----不检查
  argsIgnorePattern?: RegExp; //忽略特定格式函数参数
  caughtErrors: "all" | "none"; //处理捕获的错误
  caughtErrorsIgnorePattern?: RegExp; //忽略特定
  destructuredArrayIgnorePattern?: RegExp; //忽略解构数组
  ignoreClassWithStaticInitBlock: boolean; //忽略静态代码块
  ignoreRestSiblings: boolean; //结构赋值中忽略兄弟元素->它控制在使用**对象解构赋值（destructuring）和剩余属性（rest property）**时，是否将剩余属性的同级属性视为未使用的变量。
  reportUsedIgnorePattern: boolean; //是否报告那些匹配忽略模式的变量
  vars: "all" | "local"; //处理变脸范围all全局 local允许全局
  varsIgnorePattern?: RegExp; //忽略指定匹配模式
}
const defaultOptions: TranslatedOptions = {
  args: "after-used",
  caughtErrors: "all",
  ignoreClassWithStaticInitBlock: false,
  ignoreRestSiblings: false,
  reportUsedIgnorePattern: false,
  vars: "all",
};

const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, "NoUnusedVarsCheck");
const gMetaData: BaseMetaData = {
  severity: 1,
  ruleDocPath: "docs/no-unused-vars-check.md",
  description: "Require 'compare' argument.",
};
//编译过程中检测未使用的本地变量和参数
export class NoUnusedVarsCheck implements BaseChecker {
  readonly metaData: BaseMetaData = gMetaData;
  readonly SHORT_STR: string = "sort";
  public rule: Rule;
  public defects: Defects[] = [];
  public issues: IssueReport[] = [];

  private clsMatcher: ClassMatcher = {
    matcherType: MatcherTypes.CLASS,
  };

  public registerMatchers(): MatcherCallback[] {
    const matchBuildCb: MatcherCallback = {
      matcher: this.clsMatcher,
      callback: this.check,
    };
    return [matchBuildCb];
  }

  public check = (targetClass: ArkClass) => {
    //添加特殊情况求解 （）=》 +class
    const targetFile = targetClass.getDeclaringArkFile();
    const program = ts.createProgram([targetFile.getFilePath()], {
      options: {},
      projectReferences: [],
    });

    let astRoot = AstTreeUtils.getASTNode(
      targetFile.getName(),
      targetFile.getCode()
    );
    let otherUsedGlobal: string[] = [];
    for (let child of astRoot.statements) {
      const collectes = this.loopNode(targetFile, astRoot, child, program, []);
      otherUsedGlobal.push(...collectes);
    }
    const methods = targetClass.getMethods();
    const options: Options = this.rule.option[0] as unknown as Options;
    const mergedOptions: TranslatedOptions = defaultOptions;
    this.mergedOptions(options, mergedOptions); //options参数赋值
    //获取Scene
    const arkfile = targetClass.getDeclaringArkFile();
    const scene = arkfile.getScene();
    const nousedSet: noUseVars[] = [];
    //判定当前类是否被使用
    if (
      targetClass.getName() !== "%dflt" &&
      !this.methodOrClassUsed(scene, targetClass.getSignature(), true)
    ) {
      //class类static问题遗留
    }

    // scene.getMethods()
    //获取变量---- 获取参数---判断是否被使用
    let unuseds = nousedSet.concat(
      this.getNoUsedVars(scene, methods, mergedOptions, otherUsedGlobal)
    );
    //对结果进行过滤
    unuseds = this.filterUnuseds(mergedOptions, unuseds);
    //报错信息组装
    for (const unused of unuseds) {
      this.addIssueReport(unused);
    }
  };

  //进行option参数赋值
  mergedOptions(options: Options, mergedOptions: TranslatedOptions) {
    if (typeof options === "string") {
      mergedOptions.vars = options;
    } else {
      // 如果 options 是对象类型，合并属性到 mergedOptions
      if (options?.args) {
        mergedOptions.args = options.args;
      }
      if (options?.argsIgnorePattern) {
        mergedOptions.argsIgnorePattern = new RegExp(options.argsIgnorePattern);
      }
      if (options?.caughtErrors) {
        mergedOptions.caughtErrors = options.caughtErrors;
      }
      if (options?.caughtErrorsIgnorePattern) {
        mergedOptions.caughtErrorsIgnorePattern = new RegExp(
          options.caughtErrorsIgnorePattern
        );
      }
      if (options?.destructuredArrayIgnorePattern) {
        mergedOptions.destructuredArrayIgnorePattern = new RegExp(
          options.destructuredArrayIgnorePattern
        );
      }
      if (options?.ignoreClassWithStaticInitBlock !== undefined) {
        mergedOptions.ignoreClassWithStaticInitBlock =
          options.ignoreClassWithStaticInitBlock;
      }
      if (options?.ignoreRestSiblings !== undefined) {
        mergedOptions.ignoreRestSiblings = options.ignoreRestSiblings;
      }
      if (options?.reportUsedIgnorePattern !== undefined) {
        mergedOptions.reportUsedIgnorePattern = options.reportUsedIgnorePattern;
      }
      if (options?.vars) {
        mergedOptions.vars = options.vars;
      }
      if (options?.varsIgnorePattern) {
        mergedOptions.varsIgnorePattern = new RegExp(options.varsIgnorePattern);
      }
    }
  }

  //获取未使用集合
  private getNoUsedVars(
    scene: Scene,
    methods: ArkMethod[],
    mergedOptions: TranslatedOptions,
    otherUsedGlobal: string[]
  ): noUseVars[] {
    let nousedSet: noUseVars[] = [];
    let usedAllGlobalsKeys: string[] = []; //存放全局被使用变量最后进行筛选(最优解)
    let usedArrayPartnGlobalsKeys: string[] = []; //存放全局被使用变量最后进行筛选(最优解)
    //处理函数
    for (const method of methods) {
      if (method.getName().startsWith("%")) {
        continue;
      }
      const method_name = method.getDeclaringArkClass().getName();
      //如果是类中
      if (method.getDeclaringArkClass().getName() !== "%dflt") {
        continue;
      }
      //判断函数是否被调用过
      if (!this.methodOrClassUsed(scene, method.getSignature(), false)) {
        nousedSet.push({
          varType: VarType.Method,
          stmt: method.getBody()?.getCfg().getStmts()[0] ?? ({} as Stmt),
          declareStmt: method.getBody()?.getCfg().getStmts()[0] ?? ({} as Stmt),
          arkMethod: method,
          name: method.getName(),
        });
      }
    }

    for (const method of methods) {
      const methodStmts = method.getBody()?.getCfg().getStmts() ?? [];

      // 获取该方法的所有引用（调用位置）
      //..............判定函数是否被使用暂时忽略
      // const stmts =method.getBody()?.getCfg().getStmts()??[];
      //存放解构参数特殊处理
      const arrayBindingPattern = (
        method.getParameters() as unknown as Method_Param[]
      ).filter((param) => param.name === "ArrayBindingPattern");
      //处理对象中包含的[]解构的
      const objArrayBindingPattern = (
        method.getParameters() as unknown as Method_Param[]
      ).filter((param) => param.name === "ObjectBindingPattern");
      // 访问 objElements，确保 objArrayBindingPattern 存在
      // const objElements = objArrayBindingPattern?.objElements ?? [];
      //垃圾代码开始了，开始堆叠屎山
      let objArrayBindingPatternNames: {
        name?: string;
        methodParamIndex: number;
        elementIndex: number;
      }[] = [];
      if (objArrayBindingPattern.length > 0) {
        objArrayBindingPatternNames = method
          .getParameters()
          .flatMap((param, paramIndex) =>
            this.extractObjectArrayPatterns(
              method.getCode()?.toString() ?? ""
            ).flatMap(
              (objParam) =>
                objParam.arrayElements
                  ?.map((element, elementIndex) => ({
                    name: element.name,
                    methodParamIndex: paramIndex, // 确保这里是 method.getParameters() 的索引
                    elementIndex: elementIndex, // arrayElements 内部索引
                  }))
                  .filter((item) => Boolean(item.name)) || []
            )
          );
      }
      // 提取所有 arrayElements 的 name 属性
      // const arrayElementNames = arrayBindingPattern.flatMap(param => param.arrayElements?.map(element => element.name).filter((name): name is string => Boolean(name)) || []);
      // 提取所有 arrayElements 的 name 属性，并记录对应的 method.getParameters() 中的下标
      const arrayBindingPatternNames = arrayBindingPattern.flatMap(
        (param, paramIndex) =>
          param.arrayElements
            ?.map((element, elementIndex) => ({
              name: element.name,
              methodParamIndex: paramIndex, // method.getParameters() 中的下标
              elementIndex: elementIndex, // arrayElements 中的下标
            }))
            .filter((item) => Boolean(item.name)) || []
      );
      const arrayElementNames = [
        ...objArrayBindingPatternNames,
        ...arrayBindingPatternNames,
      ]; //2025-02-08 填坑
      //获取所有被使用的全局变量(arrayElementNames 在其中)
      const usedGlobals = method.getBody()?.getUsedGlobals();
      const globalKeys = usedGlobals ? Array.from(usedGlobals.keys()) : [];
      usedAllGlobalsKeys = usedAllGlobalsKeys.concat(globalKeys); //放入大池子中
      //获取local模块
      const varLocal: Map<string, Local> =
        method.getBody()?.getLocals() ?? new Map<string, Local>();

      let maxProcess = 0; // 记录最大使用下标
      for (const [key, local] of varLocal) {
        const localType = local.getType() as unknown as {
          methodSignature: MethodSignature;
        };
        if (localType?.methodSignature || key === "this") continue;

        const declaringStmt = local.getDeclaringStmt() as unknown as {
          rightOp: { paramType?: any; index?: number };
        };
        const stmt = local.getDeclaringStmt();

        if (
          key !== "ArrayBindingPattern" &&
          key !== "ObjectBindingPattern" &&
          !declaringStmt?.rightOp?.paramType
        ) {
          if (stmt instanceof ArkAssignStmt) {
            const left = stmt.getLeftOp() as Var_base;
            const leftName = left?.name?.toString() ?? "";

            if (
              leftName &&
              !leftName.includes("%") &&
              !this.isVarUsed(left, false)
            ) {
              const originalText = stmt.getOriginalText()?.trim() ?? "";
              const isDestructuredArray =
                leftName.startsWith("[") && leftName.endsWith("]");
              const varInit = stmt.getRightOp().toString() !== "undefined";

              if (
                originalText.includes("...") ||
                this.isOherDeclareStmt(stmt)
              ) {
                nousedSet.push({
                  varType: VarType.Var,
                  stmt,
                  declareStmt: this.isMyselfDec(stmt),
                  name: leftName,
                  local: "local",
                  isMethodParam: false,
                  isRestSiblings: true,
                });
              } else if (originalText.split("=")[0].endsWith("]")) {
                nousedSet.push({
                  varType: VarType.ArgsP,
                  stmt,
                  declareStmt: this.isMyselfDec(stmt),
                  name: leftName,
                  local: "local",
                  isMethodParam: false,
                  isRestSiblings: true,
                });
              } else if (isDestructuredArray) {
                const vars = leftName
                  .replace(/\[|\]/g, "")
                  .split(",")
                  .map((v) => v.trim())
                  .filter((v) => v && !globalKeys.includes(v));
                vars.forEach((variable) =>
                  nousedSet.push({
                    varType: VarType.ArgsP,
                    stmt,
                    declareStmt: this.isMyselfDec(stmt),
                    name: variable,
                    local: "local",
                    isMethodParam: false,
                    varInit,
                  })
                );
              } else {
                //处理特殊情况拉姆达表达式中的的变量
                if (!otherUsedGlobal.includes(leftName)) {
                  nousedSet.push({
                    varType: VarType.Var,
                    stmt: this.isMyselfMaxDec(stmt),
                    declareStmt: this.isMyselfDec(stmt),
                    name: leftName,
                    local: "local",
                    isMethodParam: false,
                    varInit,
                  });
                }
              }
            } else if (
              leftName &&
              this.isVarUsed(left, false) &&
              mergedOptions.reportUsedIgnorePattern &&
              mergedOptions.varsIgnorePattern?.test(leftName)
            ) {
              nousedSet.push({
                varType: VarType.UsedIgnorePattern,
                stmt,
                declareStmt: this.isMyselfDec(stmt),
                name: leftName,
                local: "local",
                isMethodParam: false,
              });
            }
            const originalText = stmt.getOriginalText() ?? "";
            if (
              !method.getName().includes("%df") &&
              originalText.split("=")[0].trim().endsWith("]") &&
              stmt.getRightOp().toString().startsWith("%") &&
              stmt.getRightOp().toString().endsWith("]")
            ) {
              usedArrayPartnGlobalsKeys.push(leftName);
            }
          }
        }

        if (
          !key.includes("%dflt") &&
          key !== "ArrayBindingPattern" &&
          key !== "ObjectBindingPattern" &&
          declaringStmt?.rightOp?.paramType
        ) {
          if (stmt instanceof ArkAssignStmt) {
            const left = stmt.getLeftOp() as Var_base;
            const leftName = left?.name?.toString();
            const paramIndex = declaringStmt.rightOp.index;

            if (leftName && !this.isVarUsed(left, true)) {
              //函数内参数stmt未关联位置方案代替
              const lineNo = method.getLine() ?? -1;
              const methodInex =
                method.getCode()?.indexOf(method.getName()) ??
                0 + method.getName().length ??
                -1;
              const paramInex = method.getCode()?.indexOf(leftName) ?? -1;
              let startCol = -1;
              if (methodInex > paramInex) {
                startCol = methodInex + 1 + (paramIndex ?? 0) + leftName.length;
              } else {
                startCol = paramInex;
              }
              const position: [number, number, number] = [
                lineNo,
                startCol,
                startCol + leftName.length,
              ];
              const filePath = method.getDeclaringArkFile().getFilePath();
              nousedSet.push({
                varType: VarType.Args,
                stmt,
                declareStmt: this.isMyselfDec(stmt),
                name: leftName,
                isMethodParam: true,
                paramIndex,
                methodName: method.getName(),
                argPosion: position,
                filePath: filePath,
              });
            } else {
              maxProcess = Math.max(maxProcess, paramIndex ?? 0);
            }
          }
        }
      }
      nousedSet = nousedSet.map((item) =>
        item.methodName === method.getName()
          ? { ...item, parammaxUsedIndex: maxProcess }
          : item
      );
      //处理特殊情况
      for (const stmt of methodStmts) {
        if (stmt instanceof ArkAssignStmt) {
          const left = stmt.getLeftOp() as Var_base;
          //是解构类型---->特殊处理
          if (left.name === VarType.ArgsP) {
            // 筛选出 arrayElementNames 中不在 globalKeys 中的元素
            const unusedArrayElements = arrayElementNames.filter(
              (
                item
              ): item is {
                name: string;
                methodParamIndex: number;
                elementIndex: number;
              } => item.name !== undefined && !globalKeys.includes(item.name)
            );
            for (const unusedParam of unusedArrayElements) {
              const lineNo = method.getLine() ?? -1;
              const methodInex =
                method.getCode()?.indexOf(method.getName()) ??
                0 + method.getName().length ??
                -1;
              const paramInex =
                method.getCode()?.indexOf(unusedParam.name) ?? -1;
              let startCol = -1;
              if (methodInex > paramInex) {
                startCol =
                  methodInex +
                  1 +
                  (unusedParam.methodParamIndex ?? 0) +
                  unusedParam.name.length;
              } else {
                startCol = paramInex;
              }
              const position: [number, number, number] = [
                lineNo,
                startCol,
                startCol + unusedParam.name.length,
              ];
              const filePath = method.getDeclaringArkFile().getFilePath();
              nousedSet.push({
                varType: VarType.ArgsP,
                stmt: stmt,
                name: unusedParam.name,
                declareStmt: this.isMyselfDec(stmt),
                isMethodParam: true,
                paramIndex: unusedParam.methodParamIndex,
                methodName: method.getName(),
                argPosion: position,
                filePath: filePath,
              });
            }
          }
          //2025-02-08
          if (left.name === "ObjectBindingPattern") {
            // 筛选出 arrayElementNames 中不在 globalKeys 中的元素
            const unusedArrayElements = arrayElementNames.filter(
              (
                item
              ): item is {
                name: string;
                methodParamIndex: number;
                elementIndex: number;
              } => item.name !== undefined && !globalKeys.includes(item.name)
            );
            for (const unusedParam of unusedArrayElements) {
              const lineNo = method.getLine() ?? -1;
              const methodInex =
                method.getCode()?.indexOf(method.getName()) ??
                0 + method.getName().length ??
                -1;
              const paramInex =
                method.getCode()?.indexOf(unusedParam.name) ?? -1;
              let startCol = -1;
              if (methodInex > paramInex) {
                startCol =
                  methodInex +
                  1 +
                  (unusedParam.methodParamIndex ?? 0) +
                  unusedParam.name.length;
              } else {
                startCol = paramInex;
              }
              const position: [number, number, number] = [
                lineNo,
                startCol,
                startCol + unusedParam.name.length,
              ];
              const filePath = method.getDeclaringArkFile().getFilePath();
              nousedSet.push({
                varType: VarType.ArgsP,
                stmt: stmt,
                name: unusedParam.name,
                declareStmt: this.isMyselfDec(stmt),
                isMethodParam: true,
                paramIndex: unusedParam.methodParamIndex,
                arkMethod: method,
                methodName: method.getName(),
                argPosion: position,
                filePath: filePath,
              });
            }
          }
          //常规变量
          if (
            left.name &&
            left.name != "this" &&
            !this.isVarUsed(left, false)
          ) {
            //判断是否是全局的
            if (globalKeys.includes(left.name)) {
              nousedSet.push({
                varType: VarType.Var,
                stmt: stmt,
                declareStmt: this.isMyselfDec(stmt),
                name: left.name.toString(),
                local: "all",
              });
            }
          }
        }
      }
    }
    return nousedSet;
  }

  // 判断是否被使用
  private isVarUsed(left: Var_base, ismethodParams: boolean): boolean {
    // 如果没有 usedStmts 直接返回 false
    if (!left.usedStmts) {
      return false;
    }
    if (ismethodParams && left.usedStmts.length > 0) {
      return true;
    }
    let originalText = "";
    // 遍历所有语句
    for (const stmt of left.usedStmts) {
      // 如果原始文本重复，跳过
      const stmtText = stmt.getOriginalText();
      if (originalText === stmtText) {
        continue;
      }
      // 如果 name 不相等，说明有使用，直接返回 true
      if (
        stmt instanceof ArkAssignStmt &&
        left.declaringStmt !== (stmt.getLeftOp() as Var_base).declaringStmt
      ) {
        return true;
      }
      if (stmt instanceof ArkInvokeStmt) {
        return true;
      }
      originalText = stmtText ?? ""; // 缓存原始文本，避免重复调用
    }
    // 如果没有返回 true，表示没有使用
    return false;
  }

  private methodOrClassUsed(
    scene: Scene,
    signature: MethodSignature | ClassSignature,
    isClass: boolean
  ): boolean {
    const arkMethods = scene.getMethods();
    // 遍历所有方法
    for (const arkMethod of arkMethods) {
      //进行过滤处理(防止迭代的情况发生)
      if (arkMethod.getSignature() === signature) {
        continue;
      }
      const stmts = arkMethod.getBody()?.getCfg().getStmts() ?? [];
      // 检查每个语句
      for (const stmt of stmts) {
        if (isClass && this.isClassAssigned(stmt, signature)) {
          return true;
        } else if (!isClass && this.isMethodInvoked(stmt, signature)) {
          return true;
        }
      }
    }
    return false;
  }

  // 辅助函数：检查类是否被赋值
  private isClassAssigned(
    stmt: Stmt,
    signature: ClassSignature | MethodSignature
  ): boolean {
    if (stmt instanceof ArkAssignStmt) {
      const right = stmt.getRightOp() as unknown as {
        classType: { classSignature?: ClassSignature };
      };
      const left = stmt.getLeftOp() as unknown as { name: string };
      // 如果赋值的右操作是目标类，并且不是 `this`和默认函数(扫描单个文件)
      return (
        right.classType?.classSignature === signature &&
        left.name !== "this" &&
        left.name !== "%dflt"
      );
    }
    return false;
  }

  // 辅助函数：检查方法是否被调用
  private isMethodInvoked(
    stmt: Stmt,
    signature: MethodSignature | ClassSignature
  ): boolean {
    const invokeExpr = CheckerUtils.getInvokeExprFromStmt(stmt);
    return invokeExpr?.getMethodSignature() === signature;
  }

  // 辅助函数: 判断stmt是否在当前文件stmts 的定义语句中
  private isOherDeclareStmt(stmt: Stmt): boolean {
    for (const st of stmt?.getCfg()?.getStmts() ?? []) {
      if (st instanceof ArkAssignStmt) {
        const left = st.getLeftOp() as Var_base;
        if (
          left.declaringStmt === stmt &&
          (st.getOriginalText()?.includes("...") ?? false)
        ) {
          return true;
        }
      }
    }
    return false;
  }

  //获取未使用的自调用最后一个(填坑--->20250207)无法通过usedStmt只能遍历全部 ----注意无需判断是否被使用(大条件下已经是未使用)
  private isMyselfDec(stmt: Stmt): Stmt {
    let stmto = stmt;
    if (stmt instanceof ArkAssignStmt) {
      const left = stmt.getLeftOp() as Var_base;
      if (left.declaringStmt) {
        stmto = left.declaringStmt;
      }
    }
    return stmto;
  }

  //最后调用点
  private isMyselfMaxDec(stmt: Stmt): Stmt {
    let stmto = stmt;
    const stms = stmt?.getCfg()?.getStmts() ?? [];
    for (const st of stms) {
      if (st instanceof ArkAssignStmt) {
        const left = st.getLeftOp() as Var_base;
        if (left.declaringStmt === stmt) {
          stmto = st;
        }
      }
    }
    return stmto;
  }

  //获取过滤后的结果
  private filterUnuseds(
    mergedOptions: TranslatedOptions,
    unuseds: noUseVars[]
  ) {
    //开启检查
    //1.本地检查
    if (mergedOptions.vars === "local") {
      unuseds = unuseds.filter(
        (item) => !(item.varType === VarType.Var && item.local === "all")
      );
    }
    //1.1是否过滤变量
    if (mergedOptions.varsIgnorePattern) {
      unuseds = unuseds.filter(
        (item) =>
          !(
            item.varType === VarType.Var &&
            mergedOptions.varsIgnorePattern?.test(item.name.toString())
          )
      );
    }
    //2.函数参数 (忽略最后调用之前--默认值)
    if (mergedOptions.args === "after-used") {
      unuseds = unuseds.filter(
        (item) => !((item.parammaxUsedIndex ?? -1) > (item.paramIndex ?? -1))
      );
    }
    //2.1 参数全部检索
    if (mergedOptions.args === "all") {
      // unuseds =unuseds.filter(item => !((item.parammaxUsedIndex ?? -1) < (item.paramIndex ?? -1)));已经默认
    }
    //2.2 忽略所有参数
    if (mergedOptions.args === "none") {
      unuseds = unuseds.filter((item) => !item.isMethodParam); //过滤所有的函数参数
    }
    //2.3 过滤正则匹配
    //1.1是否过滤变量
    if (mergedOptions.argsIgnorePattern) {
      unuseds = unuseds.filter(
        (item) =>
          !(
            item.varType === VarType.Args &&
            mergedOptions.argsIgnorePattern?.test(item.name.toString())
          )
      );
    }
    //3.1 是否错误代码块参数无需逻辑已默认---》all
    //3.2 忽略错误代码块参数
    if (mergedOptions.caughtErrors === "none") {
      unuseds = unuseds.filter((item) => !(item.varType === VarType.Catch)); //过滤掉错误代码块参数
    }
    //3.3 过滤正则表达式
    if (mergedOptions.caughtErrorsIgnorePattern) {
      unuseds = unuseds.filter(
        (item) =>
          !(
            item.varType === VarType.Catch &&
            mergedOptions.caughtErrorsIgnorePattern?.test(item.name.toString())
          )
      );
    }
    //4.1 destructuredArrayIgnorePattern
    if (mergedOptions.destructuredArrayIgnorePattern) {
      unuseds = unuseds.filter(
        (item) =>
          !(
            item.varType === VarType.ArgsP &&
            mergedOptions.destructuredArrayIgnorePattern?.test(
              item.name.toString()
            )
          )
      );
    }
    //5.1 ignoreRestSiblings 忽略解构同级
    if (mergedOptions.ignoreRestSiblings) {
      unuseds = unuseds.filter(
        (item) => !(item.varType === VarType.Var && item.isRestSiblings)
      ); //过滤掉同级
    }
    //6.1 忽略 class-> static
    if (mergedOptions.ignoreClassWithStaticInitBlock) {
      //暂时获取不到static块待遇处理
      //..............
    }
    //7.1 reportUsedIgnorePattern 将匹配对象报错  提前处理(基础处理时已处理)
    if (mergedOptions.reportUsedIgnorePattern) {
      unuseds = unuseds.filter(
        (item) => !(item.varType === VarType.UsedIgnorePattern)
      );
    }
    return unuseds;
  }

  //辅助函数: 通过正则获取函数特殊情况ObjectArrayPatterns
  private extractObjectArrayPatterns(paramStr: string) {
    const regex = /(\w+):\s*(\[[^\]]+\])/g; // 匹配 `p: [_q, r]`
    const matches = [];
    let match;
    while ((match = regex.exec(paramStr)) !== null) {
      matches.push({
        paramName: match[1], // 'p'
        arrayElements: match[2]
          .replace(/^\[|\]$/g, "")
          .split(",")
          .map((name) => ({
            name: name.trim(), // 去掉多余空格
          })),
      });
    }

    return matches;
  }

  //装配描述信息
  private addDescription(noUseVar: noUseVars): string {
    switch (noUseVar.varType) {
      case VarType.Var:
        return noUseVar.varInit
          ? `'${noUseVar.name}' is assigned a value but never used.`
          : `'${noUseVar.name}' is defined but never used.`;
      case VarType.Class:
        return `'${noUseVar.name}' is defined but never used.`;
      case VarType.Method:
        return `'${noUseVar.name}' is defined but never used.`;
      case VarType.Args:
        return `'${noUseVar.name}' is defined but never used.`;
      case VarType.ArgsP:
        return `'${noUseVar.name}' is defined but never used.`;
      case VarType.Catch:
        return `'${noUseVar.name}' is defined but never used.`;
      case VarType.Static:
        return `'${noUseVar.name}' is defined but never used.`;
      case VarType.UsedIgnorePattern:
        return `'${noUseVar.name}' is defined but never used.`;
        ``;
      default:
        return "Unknown type.";
    }
  }

  private addIssueReport(noUseVar: noUseVars) {
    const severity = this.rule.alert ?? this.metaData.severity;
    const warnInfo = this.getLineAndColumn(noUseVar);
    if (
      (noUseVar.varType == VarType.Args || noUseVar.varType == VarType.ArgsP) &&
      noUseVar.argPosion
    ) {
      warnInfo.line = noUseVar.argPosion[0];
      warnInfo.startCol = noUseVar.argPosion[1];
      warnInfo.endCol = noUseVar.argPosion[2];
      warnInfo.filePath = noUseVar.filePath ?? "";
    }
    let defect = new Defects(
      warnInfo.line,
      warnInfo.startCol,
      warnInfo.endCol,
      this.addDescription(noUseVar),
      severity,
      this.rule.ruleId,
      warnInfo.filePath,
      this.metaData.ruleDocPath,
      true,
      false,
      false
    );
    this.issues.push(new IssueReport(defect, undefined));
    RuleListUtil.push(
      defect
      );
  }
  private getLineAndColumn(noUseVar: noUseVars) {
    // Ensure stmt is defined and has the method `getOriginPositionInfo`
    if (
      noUseVar.stmt &&
      typeof noUseVar.stmt?.getOriginPositionInfo === "function"
    ) {
      const originPosition = noUseVar.stmt?.getOriginPositionInfo();
      const line =
        originPosition.getLineNo() > -1
          ? originPosition.getLineNo()
          : noUseVar.arkMethod?.getLine() ?? -1;

      const arkFile = noUseVar.stmt
        .getCfg()
        ?.getDeclaringMethod()
        .getDeclaringArkFile();

      if (arkFile) {
        const originText = noUseVar.arkMethod
          ? noUseVar.arkMethod.getCode()
          : noUseVar.stmt.getOriginalText() ?? "";

        let startCol =
          originPosition.getColNo() > -1
            ? originPosition.getColNo()
            : noUseVar.arkMethod?.getColumn() ?? -1;

        const pos = originText
          ? originText.indexOf(noUseVar.name.toString())
          : -1;

        if (pos !== -1) {
          startCol += pos;
          const endCol = startCol + noUseVar.name.toString().length - 1;
          const originPath = arkFile.getFilePath();
          return { line, startCol, endCol, filePath: originPath };
        }
      } else {
        logger.debug("arkFile is null");
      }
    } else {
      // Log or handle cases where stmt doesn't have `getOriginPositionInfo` method
      logger.warn(
        "getOriginPositionInfo method is not available on stmt or stmt is undefined."
      );
    }

    // Default return if nothing is found
    return { line: -1, startCol: -1, endCol: -1, filePath: "" };
  }
  //获取所有箭头函数使用的全局变量
  loopNode(
    targetFile: ArkFile,
    sourceFile: ts.SourceFile,
    aNode: ts.Node,
    program: ts.Program,
    usedGlobalP: string[] = [] // 在递归调用时保持所有的全局变量
  ) {
    const children = aNode.getChildren();

    for (const node of children) {
      if (ts.isArrowFunction(node)) {
        // 提取箭头函数的参数
        const params: string[] = [];
        const cd = node.parameters;
        for (const cdd of cd) {
          if (ts.isParameter(cdd)) {
            const cfd = cdd.getChildren();
            for (const cds of cfd) {
              if (ts.isIdentifier(cds)) {
                params.push(cds.getText());
              }
            }
          }
        }

        // 检查箭头函数体内的全局变量（比如 num）
        if (ts.isBlock(node.body)) {
          // 如果箭头函数体是块语句，递归检查每个子节点
          node.body.statements.forEach((statement) => {
            if (ts.isExpressionStatement(statement)) {
              const expr = statement.expression;
              if (
                ts.isIdentifier(expr) &&
                params.indexOf(expr.getText()) === -1
              ) {
                // 如果是标识符，且不在参数列表中，视为全局变量
                usedGlobalP.push(expr.getText());
              }
            }
          });
        } else if (
          ts.isIdentifier(node.body) &&
          params.indexOf(node.body.getText()) === -1
        ) {
          // 如果箭头函数体是一个简单的标识符（例如 num），并且它不在参数列表中
          usedGlobalP.push(node.body.getText());
        }

        // 递归调用，继续遍历子节点
        if (node.getChildren().length > 0) {
          this.loopNode(targetFile, sourceFile, node, program, usedGlobalP);
        }
      } else {
        // 对于非箭头函数节点，继续递归遍历子节点
        ts.forEachChild(node, (child) => {
          this.loopNode(targetFile, sourceFile, child, program, usedGlobalP);
        });
      }
    }

    return usedGlobalP; // 返回最终的所有 usedGlobalP
  }
}
